{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4Pjmz-RORV8E"
      },
      "source": [
        "# Run pipeline workflows\n",
        "\n",
        "txtai has a growing list of models available through it's pipeline framework. Pipelines wrap a machine learning model and transform data. Currently, pipelines can wrap Hugging Face models, Hugging Face pipelines or PyTorch models (support for TensorFlow is in the backlog).\n",
        "\n",
        "The following is a list of the currently implemented pipelines.\n",
        "\n",
        "* **Questions** - Answer questions using a text context\n",
        "* **Labels** - Apply labels to text using a zero-shot classification model. Also supports similarity comparisions.\n",
        "* **Summary** - Abstractive text summarization\n",
        "* **Textractor** - Extract text from documents\n",
        "* **Transcription** - Transcribe audio to text\n",
        "* **Translation** - Machine translation\n",
        "\n",
        "Pipelines are great and make using a variety of machine learning models easier. But what if we want to glue the results of different pipelines together? For example, extract text, summarize it, translate it to English and load it into an Embedding index. That would require code to join those operations together in an efficient manner.\n",
        "\n",
        "Enter workflows. Workflows are a simple yet powerful construct that takes a callable and returns elements. Workflows don't know they are working with pipelines but enable efficient processing of pipeline data. Workflows are streaming by nature and work on data in batches, allowing large volumes of data to be processed efficiently."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Dk31rbYjSTYm"
      },
      "source": [
        "# Install dependencies\n",
        "\n",
        "Install `txtai` and all dependencies. Since this notebook is using optional pipelines/workflows, we need to install the pipeline and workflow extras package."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XMQuuun2R06J"
      },
      "source": [
        "%%capture\n",
        "!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline,workflow] sacremoses\n",
        "\n",
        "# Get test data\n",
        "!wget -N https://github.com/neuml/txtai/releases/download/v2.0.0/tests.tar.gz\n",
        "!tar -xvzf tests.tar.gz"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I1dNQE7WT4kE"
      },
      "source": [
        "# Create a series of pipelines to use in this notebook"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "w4YqwBJaT4QD"
      },
      "source": [
        "%%capture\n",
        "from txtai.pipeline import Summary, Textractor, Transcription, Translation\n",
        "\n",
        "# Summary instance\n",
        "summary = Summary()\n",
        "\n",
        "# Text extraction\n",
        "textractor = Textractor()\n",
        "\n",
        "# Transcription instance\n",
        "transcribe = Transcription(\"facebook/wav2vec2-large-960h\")\n",
        "\n",
        "# Create a translation instance\n",
        "translate = Translation()"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PNPJ95cdTKSS"
      },
      "source": [
        "# Basic workflow\n",
        "\n",
        "The following shows a basic workflow in action!"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nTDwXOUeTH2-",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "906d4354-cf29-4593-a790-8c175d981dee"
      },
      "source": [
        "from txtai.workflow import Workflow, Task\n",
        "\n",
        "# Workflow that translate text to French\n",
        "workflow = Workflow([Task(lambda x: translate(x, \"fr\"))])\n",
        "\n",
        "# Data to run through the pipeline\n",
        "data = [\"The sky is blue\", \"Forest through the trees\"]\n",
        "\n",
        "# Workflows are generators for efficiency, read results to list for display\n",
        "list(workflow(data))"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['Le ciel est bleu', 'Forêt à travers les arbres']"
            ]
          },
          "metadata": {},
          "execution_count": 13
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wicr0CAYRWZ0"
      },
      "source": [
        "This isn't too different from previous pipeline examples. The only difference is data is feed through the workflow. In this example, the workflow calls the translation pipeline and translates text to French. Let's look at a more complex example."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0EeD8m6FR5cH"
      },
      "source": [
        "# Multistep workflow\n",
        "\n",
        "The following workflow reads a series of audio files, transcribes them to text and translates the text to French. This is based on the classic txtai example from [Introducing txtai](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/01_Introducing_txtai.ipynb).\n",
        "\n",
        "Workflows take two main parameters. The action to execute which is a callable and a pattern to filter data with. Data that is accepted by the filter will be processed, otherwise it will be passed through to the next task."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OF2G5-OiSBzy",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "e5c74089-1916-4bbd-93d3-9e25b1fe4ee5"
      },
      "source": [
        "from txtai.workflow import FileTask\n",
        "\n",
        "tasks = [\n",
        "    FileTask(transcribe, r\"\\.wav$\"),\n",
        "    Task(lambda x: translate(x, \"fr\"))\n",
        "]\n",
        "\n",
        "# List of files to process\n",
        "data = [\n",
        "  \"txtai/US_tops_5_million.wav\",\n",
        "  \"txtai/Canadas_last_fully.wav\",\n",
        "  \"txtai/Beijing_mobilises.wav\",\n",
        "  \"txtai/The_National_Park.wav\",\n",
        "  \"txtai/Maine_man_wins_1_mil.wav\",\n",
        "  \"txtai/Make_huge_profits.wav\"\n",
        "]\n",
        "\n",
        "# Workflow that translate text to French\n",
        "workflow = Workflow(tasks)\n",
        "\n",
        "# Run workflow\n",
        "list(workflow(data))"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[\"Les cas de virus U sont en tête d'un million\",\n",
              " \"La dernière plate-forme de glace entièrement intacte du Canada s'est soudainement effondrée en formant un berge de glace de taille manhatten\",\n",
              " \"Bagage mobilise les embarcations d'invasion le long des côtes à mesure que les tensions tiwaniennes s'intensifient\",\n",
              " \"Le service des parcs nationaux met en garde contre le sacrifice d'amis plus lents dans une attaque nue\",\n",
              " \"L'homme principal gagne du billet de loterie\",\n",
              " \"Faire d'énormes profits sans travailler faire jusqu'à cent mille dollars par jour\"]"
            ]
          },
          "metadata": {},
          "execution_count": 14
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PN08rnrQU1hx"
      },
      "source": [
        "# Complex workflow\n",
        "\n",
        "Let's put this all together into a full-fledged workflow to build an embeddings index. This workflow will work with both documents and audio files. Documents will have text extracted and summarized. Audio files will be transcribed. Both results will be joined, translated into French and loaded into an Embeddings index."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "coZJw_1yU1Sq",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "213b34d5-157f-4548-8788-ac29cb4039dd"
      },
      "source": [
        "from txtai.embeddings import Embeddings, Documents\n",
        "from txtai.workflow import FileTask, WorkflowTask\n",
        "\n",
        "# Embeddings index\n",
        "embeddings = Embeddings({\"path\": \"sentence-transformers/paraphrase-multilingual-mpnet-base-v2\", \"content\": True})\n",
        "documents = Documents()\n",
        "\n",
        "# List of files to process\n",
        "files = [\n",
        "  \"txtai/article.pdf\",\n",
        "  \"txtai/US_tops_5_million.wav\",\n",
        "  \"txtai/Canadas_last_fully.wav\",\n",
        "  \"txtai/Beijing_mobilises.wav\",\n",
        "  \"txtai/The_National_Park.wav\",\n",
        "  \"txtai/Maine_man_wins_1_mil.wav\",\n",
        "  \"txtai/Make_huge_profits.wav\"\n",
        "]\n",
        "\n",
        "data = [(x, element, None) for x, element in enumerate(files)]\n",
        "\n",
        "# Workflow that extracts text and builds a summary\n",
        "articles = Workflow([\n",
        "    FileTask(textractor),\n",
        "    Task(summary)\n",
        "])\n",
        "\n",
        "# Define workflow tasks. Workflows can also be tasks!\n",
        "tasks = [\n",
        "    WorkflowTask(articles, r\".\\.pdf$\"),\n",
        "    FileTask(transcribe, r\"\\.wav$\"),\n",
        "    Task(lambda x: translate(x, \"fr\")),\n",
        "    Task(documents.add, unpack=False)\n",
        "]\n",
        "\n",
        "# Workflow that translate text to French\n",
        "workflow = Workflow(tasks)\n",
        "\n",
        "# Run workflow and show results to be indexed\n",
        "for x in workflow(data):\n",
        "  print(x)\n",
        "\n",
        "# Build the embeddings index\n",
        "embeddings.index(documents)\n",
        "\n",
        "# Cleanup temporary storage\n",
        "documents.close()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "(0, \"Txtai, un moteur de recherche alimenté par l'IA construit sur Transformers, permet la recherche basée sur la compréhension du langage naturel (NLU) dans n'importe quelle application. Le champ de traitement du langage naturel (NLP) évolue rapidement avec un certain nombre de nouveaux développements. Le moteur de recherche open-source est open source et disponible sur GitHub.\", None)\n",
            "(1, \"Les cas de virus U sont en tête d'un million\", None)\n",
            "(2, \"La dernière plate-forme de glace entièrement intacte du Canada s'est soudainement effondrée en formant un berge de glace de taille manhatten\", None)\n",
            "(3, \"Bagage mobilise les embarcations d'invasion le long des côtes à mesure que les tensions tiwaniennes s'intensifient\", None)\n",
            "(4, \"Le service des parcs nationaux met en garde contre le sacrifice d'amis plus lents dans une attaque nue\", None)\n",
            "(5, \"L'homme principal gagne du billet de loterie\", None)\n",
            "(6, \"Faire d'énormes profits sans travailler faire jusqu'à cent mille dollars par jour\", None)\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "n6i-xhJya8o4"
      },
      "source": [
        "# Query for results in French"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cHbjivUOaUGu",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "0da8d8cb-dac6-4cad-ef00-a096b44533cf"
      },
      "source": [
        "# Run a search query and show the result.\n",
        "embeddings.search(\"changement climatique\", 1)[0]"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'id': '2',\n",
              " 'score': 0.2982647716999054,\n",
              " 'text': \"La dernière plate-forme de glace entièrement intacte du Canada s'est soudainement effondrée en formant un berge de glace de taille manhatten\"}"
            ]
          },
          "metadata": {},
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aNerHvNpaxD4",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "f3792220-4518-4388-c7e7-c38f38f19b20"
      },
      "source": [
        "# Run a search query and show the result.\n",
        "embeddings.search(\"traitement du langage naturel\", 1)[0]"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'id': '0',\n",
              " 'score': 0.47031939029693604,\n",
              " 'text': \"Txtai, un moteur de recherche alimenté par l'IA construit sur Transformers, permet la recherche basée sur la compréhension du langage naturel (NLU) dans n'importe quelle application. Le champ de traitement du langage naturel (NLP) évolue rapidement avec un certain nombre de nouveaux développements. Le moteur de recherche open-source est open source et disponible sur GitHub.\"}"
            ]
          },
          "metadata": {},
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Configuration-driven workflow\n",
        "\n",
        "Workflows can also be defined with YAML and run as an application. Applications can run standalone or as a FastAPI instance. More information can be [found here](https://neuml.github.io/txtai/api/). "
      ],
      "metadata": {
        "id": "Sz_f9qoOMC_m"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "workflow = \"\"\"\n",
        "writable: true\n",
        "embeddings:\n",
        "  path: sentence-transformers/paraphrase-multilingual-mpnet-base-v2\n",
        "  content: True\n",
        "\n",
        "# Summarize text\n",
        "summary:\n",
        "\n",
        "# Extract text from documents\n",
        "textractor:\n",
        "\n",
        "# Transcribe audio to text\n",
        "transcription:\n",
        "  path: facebook/wav2vec2-large-960h\n",
        "\n",
        "# Translate text between languages\n",
        "translation:\n",
        "\n",
        "workflow:\n",
        "  summarize:\n",
        "    tasks:\n",
        "      - action: textractor\n",
        "        task: file\n",
        "      - summary\n",
        "  index:\n",
        "    tasks:\n",
        "      - action: summarize\n",
        "        select: '\\\\.pdf$'\n",
        "      - action: transcription\n",
        "        select: '\\\\.wav$'\n",
        "        task: file\n",
        "      - action: translation\n",
        "        args: ['fr']\n",
        "      - action: index\n",
        "\"\"\"\n",
        "\n",
        "# Create and run the workflow\n",
        "from txtai.app import Application\n",
        "\n",
        "# Create and run the workflow\n",
        "app = Application(workflow)\n",
        "list(app.workflow(\"index\", files))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "HoVlk_vNJKHY",
        "outputId": "34b68bcb-a6d5-4029-9bf2-f33e4381d1bc"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[\"Txtai, un moteur de recherche alimenté par l'IA construit sur Transformers, permet la recherche basée sur la compréhension du langage naturel (NLU) dans n'importe quelle application. Le champ de traitement du langage naturel (NLP) évolue rapidement avec un certain nombre de nouveaux développements. Le moteur de recherche open-source est open source et disponible sur GitHub.\",\n",
              " \"Les cas de virus U sont en tête d'un million\",\n",
              " \"La dernière plate-forme de glace entièrement intacte du Canada s'est soudainement effondrée en formant un berge de glace de taille manhatten\",\n",
              " \"Bagage mobilise les embarcations d'invasion le long des côtes à mesure que les tensions tiwaniennes s'intensifient\",\n",
              " \"Le service des parcs nationaux met en garde contre le sacrifice d'amis plus lents dans une attaque nue\",\n",
              " \"L'homme principal gagne du billet de loterie\",\n",
              " \"Faire d'énormes profits sans travailler faire jusqu'à cent mille dollars par jour\"]"
            ]
          },
          "metadata": {},
          "execution_count": 18
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Run a search query and show the result.\n",
        "app.search(\"changement climatique\", 1)[0]"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "a_klVZAXHJcw",
        "outputId": "33229268-0f98-4ca1-af7d-212bcbde6482"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'id': '2',\n",
              " 'score': 0.2982647716999054,\n",
              " 'text': \"La dernière plate-forme de glace entièrement intacte du Canada s'est soudainement effondrée en formant un berge de glace de taille manhatten\"}"
            ]
          },
          "metadata": {},
          "execution_count": 19
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Run a search query and show the result.\n",
        "app.search(\"traitement du langage naturel\", 1)[0]"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "I5xin0VNHJOu",
        "outputId": "2fbb9a93-b860-437d-c361-ee21eed75b6b"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'id': '0',\n",
              " 'score': 0.47031939029693604,\n",
              " 'text': \"Txtai, un moteur de recherche alimenté par l'IA construit sur Transformers, permet la recherche basée sur la compréhension du langage naturel (NLU) dans n'importe quelle application. Le champ de traitement du langage naturel (NLP) évolue rapidement avec un certain nombre de nouveaux développements. Le moteur de recherche open-source est open source et disponible sur GitHub.\"}"
            ]
          },
          "metadata": {},
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7zG4AimucFJs"
      },
      "source": [
        "# Wrapping up\n",
        "\n",
        "Results are good! We can see the power of workflows and how they can join a series of pipelines together in an efficient manner. Workflows can work with any callable, not just pipelines, workflows transform data from one format to another. Workflows are an exciting and promising development for txtai."
      ]
    }
  ]
}